package com.starryx.sim.mvc.net.handler.task;


import com.starryx.sim.mvc.controller.ControllerManager;
import com.starryx.sim.mvc.controller.RequestMappingWrapper;
import com.starryx.sim.mvc.util.JsonUtil;
import com.starryx.sim.mvc.util.SpringContextUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.util.AsciiString;

import java.nio.charset.StandardCharsets;

import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;


/**
 * 处理任务类，让业务与 I/O 分离
 */
public class HandleTask implements Runnable {

	private static final AsciiString CONNECTION = AsciiString.cached("Connection");

	private static final AsciiString KEEP_ALIVE = AsciiString.cached("keep-alive");

	private static final AsciiString CONTENT_TYPE = AsciiString.cached("Content-Type");

	private static final AsciiString CONTENT_LENGTH = AsciiString.cached("Content-Length");

	private RequestMappingWrapper requestMappingWrapper;

	private Object param;

	private FullHttpRequest fullHttpRequest;

	private ChannelHandlerContext ctx;

	public HandleTask(RequestMappingWrapper requestMappingWrapper, Object param, FullHttpRequest fullHttpRequest, ChannelHandlerContext ctx) {
		this.requestMappingWrapper = requestMappingWrapper;
		this.param = param;
		this.fullHttpRequest = fullHttpRequest;
		this.ctx = ctx;
	}

	@Override
	public void run() {
		ControllerManager controllerManager = SpringContextUtil.getBean(ControllerManager.class);
		Object result = controllerManager.handleRequest(requestMappingWrapper, param);
		String jsonResult = JsonUtil.toJson(result);
		byte[] responseBytes = jsonResult.getBytes(StandardCharsets.UTF_8);
		// 创建一个默认 HTTP 响应对象，并设置状态行，将转化好 HTML 文本放入其中
		FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(responseBytes));
		// 设置响应头参数
		// 设置响应体类型为 application/json，字符集为 charset=utf-8
		response.headers().set(CONTENT_TYPE, "application/json; charset=utf-8");
		// 设置响应体长度为 HTML 文本的长度
		response.headers().setInt(CONTENT_LENGTH, response.content().readableBytes());
		// todo：长连接保持的管理可以利用 LRU 缓存，设定一个值，如果超过这个值就将符合情况的连接断开
		boolean keepAlive = HttpUtil.isKeepAlive(fullHttpRequest);
		// 判断是否还保持连接，否则发送完最后一次信息就断开连接
		if (!keepAlive) {
			ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
		} else {
			response.headers().set(CONNECTION, KEEP_ALIVE);
			ctx.writeAndFlush(response);
		}
	}

}
